#include "pch.h"
#include "BitsConvert.h"


std::string RefMap = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789+/";

std::stringbuf* RefToChars(const::std::vector<uint8_t> bits)
{
	std::stringbuf* result = new std::stringbuf();
	int ArrLen = bits.size();
	int padLen = 0;
	if (ArrLen % 3 != 0) {
		padLen = 3 - (ArrLen % 3);
	}
	size_t in_len = bits.size() + padLen;
	for (int i = 0; i < in_len; i += 3) {
		std::stringbuf tempStr;
		if (i == in_len - 3 && padLen != 0) {
			if (padLen == 1) {
				uint32_t temp = ((uint32_t)bits[i]) + (((uint32_t)bits[i + 1]) << 8);
				for (int j = 0; j < 2; j++) {
					int RefCode = temp & 63;
					tempStr.sputc(RefMap[RefCode]);
					temp = temp >> 6;
				}
				tempStr.sputc(RefMap[(temp << 2)]);
				tempStr.sputc('=');
			}
			else if (padLen == 2) {
				uint32_t temp = bits[i];
				tempStr.sputc(RefMap[temp & 63]);
				tempStr.sputc(RefMap[((temp >> 6) << 4)]);
				tempStr.sputn("==", 2);
			}
		}
		else {
			uint32_t temp = (uint32_t)bits[i] + (((uint32_t)bits[i + 1]) << 8) + (((uint32_t)bits[i + 2]) << 16);
			for (int j = 0; j < 4; j++) {
				int RefCode = temp & 63;
				tempStr.sputc(RefMap[RefCode]);
				temp = temp >> 6;
			}
		}
		result->sputn(tempStr.str().c_str(), tempStr.str().length());
	}
	return result;
}

std::vector<uint8_t>* RefCharsToU8Arr(const std::string chars)
{
	std::vector<uint8_t>* arr = new std::vector<uint8_t>((chars.size() / 4) * 3);
	int arrLen = arr->size();
	for (int i = 0; i < arr->size(); i += 3) {
		const std::string tempStr = chars.substr((i / 3) * 4, 4);
		uint32_t temp = 0;
		if (tempStr.find('=') != std::string::npos) {
			int padNum = 0;
			for (int j = 3; j >= 0; j--) {
				if (tempStr[j] == '=') {
					padNum++;
					continue;
				}
				temp = (temp << 6) + RefMap.find(tempStr[j]);
			}
			if (padNum == 1) {
				temp = ((temp >> 14) << 12) + (temp & 4095);
				(*arr)[i] = temp & 255;
				(*arr)[i + 1] = (temp >> 8) & 255;
			}
			else if (padNum == 2) {
				temp = ((temp >> 10) << 6) + (temp & 63);
				(*arr)[i] = temp;
			}
			arrLen = arrLen - padNum;
		}
		else {
			for (int j = 3; j >= 0; j--) {
				temp = (temp << 6) + RefMap.find(tempStr[j]);
			}
			for (int j = 0; j < 3; j++) {
				(*arr)[i + j] = temp & 255;
				temp = temp >> 8;
			}
		}
	}
	arr->resize(arrLen);
	return arr;
}
